<template>
  <div class="workflow-canvas">
    <div ref="canvasDiv" class="canvas-container"></div>
    
    <!-- 节点参数配置弹窗 -->
    <WorkflowParamconfig />
    
    <!-- 执行结果展示弹窗 -->
    <el-dialog
      v-model="showResultDialog"
      title="执行结果"
      width="500px"
    >
      <div class="result-content">
        <el-result
          icon="success"
          title="执行完成"
          sub-title="工作流已成功执行"
        >
          <template #extra>
            <div class="result-details">
              <p v-for="(result, nodeId) in executionResults" :key="nodeId">
                <strong>{{ getNodeNameById(nodeId) }}:</strong> {{ result }}
              </p>
            </div>
          </template>
        </el-result>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, watch, nextTick } from 'vue'
import * as go from 'gojs'
import { ElDialog, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElButton, ElResult } from 'element-plus'
import { useWorkflowStore } from '@/stores/workflow'
import WorkflowParamconfig from './WorkflowParamconfig.vue'

const canvasDiv = ref(null)
let diagram = null

// 执行结果相关
const showResultDialog = ref(false)
const executionResults = ref({})

// 使用工作流状态存储
const workflowStore = useWorkflowStore()
// 初始化画布
function initDiagram() {
  const $ = go.GraphObject.make
  
  diagram = $(go.Diagram, canvasDiv.value, {
    'undoManager.isEnabled': true,
    'grid.visible': true,
    'draggingTool.isGridSnapEnabled': true,
    'animationManager.isEnabled': false,
    'linkingTool.direction': go.LinkingTool.ForwardsOnly,
    'draggingTool.dragsLink': false
  })
  
  // 定义节点模板
  diagram.nodeTemplate = $(
    go.Node,
    'Vertical',
    {
      locationSpot: go.Spot.Center,
      resizable: true,
      click: showNodeConfig
    },
    new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
    $(
      go.Panel,
      'Horizontal',
      { margin: 10 },
      // 添加节点图标
      $(
        go.Shape,
        'Circle',
        {
          width: 20,
          height: 20,
          fill: 'white',
          strokeWidth: 2,
          margin: 4
        },
        new go.Binding('figure', 'type', getTypeIcon),
        new go.Binding('fill', 'type', getTypeIconColor)
      ),
      // 节点名称
      $(
        go.TextBlock,
        {
          font: 'bold 14px sans-serif',
          textAlign: 'center',
          stroke: '#333',
          margin: new go.Margin(0, 0, 0, 5)
        },
        new go.Binding('text', 'text')
      )
    ),
    $(
      go.Shape,
      'RoundedRectangle',
      {
        strokeWidth: 2,
        fill: 'lightblue',
        portId: '',
        fromLinkable: true,
        toLinkable: true,
        cursor: 'pointer',
        desiredSize: new go.Size(160, 60)
      },
      new go.Binding('fill', 'color'),
      // 绑定节点状态颜色
      new go.Binding('fill', 'key', getNodeFillColor).ofObject()
    ),
    // 添加状态指示器
    $(
      go.Shape,
      'Circle',
      {
        width: 12,
        height: 12,
        fill: 'gray',
        stroke: 'white',
        strokeWidth: 1,
        alignment: go.Spot.TopRight,
        alignmentFocus: go.Spot.Center
      },
      new go.Binding('fill', 'key', getNodeStatusColor).ofObject()
    )
  )
  
  // 定义链接模板
  diagram.linkTemplate = $(
    go.Link,
    {
      routing: go.Link.AvoidsNodes,
      curve: go.Link.JumpOver,
      corner: 5,
      toShortLength: 4,
      relinkableFrom: false,
      relinkableTo: false
    },
    $(go.Shape, { strokeWidth: 2, stroke: '#555' }),
    $(go.Shape, { toArrow: 'Standard', stroke: null })
  )
  
  // 验证链接规则
  diagram.linkValidation = validateLink
  
  return diagram
}

// 添加获取节点图标类型的方法
function getTypeIcon(type) {
  switch (type) {
    case 'input':
      return 'folder';
    case 'process':
      return 'Gear';
    case 'output':
      return 'ThinArrow';
    default:
      return 'Rectangle';
  }
}

// 添加获取图标颜色的方法
function getTypeIconColor(type) {
  switch (type) {
    case 'input':
      return '#67C23A'; // 绿色
    case 'process':
      return '#409EFF'; // 蓝色
    case 'output':
      return '#E6A23C'; // 橙色
    default:
      return '#909399'; // 灰色
  }
}

// 根据节点状态获取填充颜色
function getNodeFillColor(nodeKey) {
  const node = diagram.findNodeForKey(nodeKey)
  if (!node) return 'lightgray'
  
  const baseColor = getNodeColor(node.data.type)
  const status = workflowStore.getNodeState(nodeKey)
  
  // 根据状态调整颜色
  switch (status) {
    case 'executing':
      return baseColor // 可以添加动画效果
    case 'completed':
      return baseColor
    default:
      return baseColor
  }
}

// 根据节点状态获取状态指示器颜色
function getNodeStatusColor(nodeKey) {
  const status = workflowStore.getNodeState(nodeKey)
  
  switch (status) {
    case 'pending':
      return 'gray'
    case 'executing':
      return 'orange'
    case 'completed':
      return 'green'
    case 'error':
      return 'red'
    default:
      return 'gray'
  }
}

// 验证链接规则（输入→处理→输出）
function validateLink(fromNode, fromPort, toNode, toPort) {
  if (!fromNode || !toNode) return false
  
  const fromType = fromNode.data.type
  const toType = toNode.data.type
  
  // 定义允许的流向
  const validFlows = {
    input: ['process', 'output'],
    process: ['process', 'output'],
    output: []
  }
  
  return validFlows[fromType]?.includes(toType) || false
}

// 显示节点配置对话框
function showNodeConfig(e, node) {
  if (!node) return
  
  const model = diagram.model
  const nodeDataArray = model.nodeDataArray
  const linkDataArray = model.linkDataArray
  const workflowData = {
    nodeDataArray: nodeDataArray.map(n => ({...n})),
    linkDataArray: linkDataArray.map(l => ({...l}))
  }
  workflowStore.setWorkflow(workflowData)

  workflowStore.openParamConfig(node.data.key)
}

// 加载工作流数据
function loadWorkflow(workflow) {
  if (!diagram) return
  
  const model = new go.GraphLinksModel()
  model.nodeDataArray = workflow.nodes.map(node => ({
    key: node.id,
    text: node.name,
    type: node.type,
    loc: `${node.position.x} ${node.position.y}`,
    color: getNodeColor(node.type),
    params: node.params || {}
  }))
  
  model.linkDataArray = workflow.edges.map(edge => ({
    from: edge.from,
    to: edge.to
  }))
  
  diagram.model = model
}

// 根据节点类型获取颜色
function getNodeColor(type) {
  // 处理节点库中的类型
  if (type === 'input') return 'lightgreen';
  if (type === 'process') return 'lightblue';
  if (type === 'output') return 'lightcoral';
  

  return 'lightgray';
}

// 获取当前工作流数据
function getWorkflow() {
  if (!diagram) return null
  
  const nodeDataArray = diagram.model.nodeDataArray
  const linkDataArray = diagram.model.linkDataArray
  
  return {
    nodes: nodeDataArray.map(node => ({
      id: node.key,
      name: node.text,
      type: node.type,
      position: {
        x: parseFloat(node.loc.split(' ')[0]),
        y: parseFloat(node.loc.split(' ')[1])
      },
      params: node.params || {}
    })),
    edges: linkDataArray.map(link => ({
      from: link.from,
      to: link.to
    }))
  }
}

// 根据节点ID获取节点名称
function getNodeNameById(nodeId) {
  if (!diagram) return nodeId
  const node = diagram.findNodeForKey(nodeId)
  return node ? node.data.text : nodeId
}

// 执行工作流
async function executeWorkflow() {
  if (!diagram) return
  
  // 重置执行状态
  workflowStore.startExecution()
  executionResults.value = {}
  
  const workflow = getWorkflow()
  if (!workflow || !workflow.nodes.length) return
  
  // 按拓扑顺序执行节点
  const executionOrder = getExecutionOrder(workflow)
  
  try {
    for (const node of executionOrder) {
      // 更新节点状态为执行中
      workflowStore.updateNodeState(node.id, 'executing')
      diagram.updateAllRelationshipsFromData()
      diagram.updateAllTargetBindings()
      
      // 模拟执行延迟
      await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000))
      
      // 模拟执行结果
      const result = await simulateNodeExecution(node)
      executionResults.value[node.id] = result
      
      // 更新节点状态为完成
      workflowStore.updateNodeState(node.id, 'completed')
      workflowStore.setExecutionResult(node.id, result)
      diagram.updateAllRelationshipsFromData()
      diagram.updateAllTargetBindings()
    }
    
    // 执行完成
    workflowStore.finishExecution()
    
    // 显示最终结果（仅对输出节点）
    const outputNodes = workflow.nodes.filter(node => node.type === 'output')
    if (outputNodes.length > 0) {
      showResultDialog.value = true
    }
  } catch (error) {
    console.error('执行工作流出错:', error)
    workflowStore.finishExecution()
  }
}

// 获取节点执行顺序（拓扑排序）
function getExecutionOrder(workflow) {
  const nodes = workflow.nodes
  const edges = workflow.edges
  
  // 构建邻接表
  const graph = {}
  const inDegree = {}
  
  // 初始化
  nodes.forEach(node => {
    graph[node.id] = []
    inDegree[node.id] = 0
  })
  
  // 构建图
  edges.forEach(edge => {
    graph[edge.from].push(edge.to)
    inDegree[edge.to]++
  })
  
  // 拓扑排序
  const queue = []
  const result = []
  
  // 将入度为0的节点加入队列
  nodes.forEach(node => {
    if (inDegree[node.id] === 0) {
      queue.push(node)
    }
  })
  
  // BFS拓扑排序
  while (queue.length > 0) {
    const node = queue.shift()
    result.push(node)
    
    // 更新邻接节点的入度
    graph[node.id].forEach(neighborId => {
      inDegree[neighborId]--
      if (inDegree[neighborId] === 0) {
        const neighborNode = nodes.find(n => n.id === neighborId)
        if (neighborNode) {
          queue.push(neighborNode)
        }
      }
    })
  }
  
  return result
}

// 模拟节点执行
async function simulateNodeExecution(node) {
  const params = node.params || {}
  
  switch (node.type) {
    case 'upload':
      return `成功上传文件，包含100个样本`
      
    case 'preprocess':
      const missingMethod = params.missingValueMethod || '均值填充'
      const filledCount = Math.floor(Math.random() * 30) + 10
      const remainingSamples = 100 - Math.floor(Math.random() * 10)
      return `预处理完成：样本 ${100}→${remainingSamples} 个，填充缺失值 ${filledCount} 处，使用${missingMethod}`
      
    case 'output':
      return `结果已保存到指定路径，包含${90 + Math.floor(Math.random() * 10)}个处理后的样本`
      
    default:
      return '节点执行完成'
  }
}

defineExpose({
  loadWorkflow,
  getWorkflow,
  executeWorkflow,
  // 添加addNode方法
  addNode(nodeData, position) {
    if (!diagram) return;
    
    // 生成唯一的节点key
    const key = `${nodeData.type}_${Date.now()}`;
    
    // 创建节点数据
    const node = {
      key: key,
      text: nodeData.name,  // 使用text属性而不是name属性
      type: nodeData.type,
      loc: `${position.x} ${position.y}`,
      color: getNodeColor(nodeData.type)
    };
    
    // 将节点添加到图表中
    diagram.model.addNodeData(node);
  }
})

onMounted(() => {
  initDiagram()
})

// 接收外部传入的工作流数据
const props = defineProps({
  workflow: {
    type: Object,
    default: null
  }
})

watch(() => props.workflow, (newWorkflow) => {
  if (newWorkflow) {
    loadWorkflow(newWorkflow)
  }
}, { immediate: true })

// 监听节点状态变化，更新图表
watch(() => workflowStore.nodeStates, () => {
  if (diagram) {
    diagram.updateAllRelationshipsFromData()
    diagram.updateAllTargetBindings()
  }
}, { deep: true })

watch(() => workflowStore.workflowData, (newData) => {
  if(diagram && newData) {
    diagram.model.commit((tx) => {
      newData.nodeDataArray.forEach(nodeData => {
        const node = diagram.findNodeForKey(nodeData.key);
        if(node) {
          diagram.model.set(node.data, 'params', nodeData.params || {});
        }
      })
    }, "update node params");
  } 
} ,{deep:true})
</script>

<style scoped>
.workflow-canvas {
  width: 100%;
  height: 100%;
}

.canvas-container {
  width: 100%;
  height: 100%;
  border: 1px solid #ccc;
  background: #fafafa;
}

.node-config-form {
  max-height: 400px;
  overflow-y: auto;
}

.result-content {
  text-align: center;
}

.result-details {
  text-align: left;
  margin-top: 20px;
  padding: 10px;
  background-color: #f5f5f5;
  border-radius: 4px;
}

.result-details p {
  margin: 5px 0;
}
</style>